#include <WiFi.h>
#include <HTTPClient.h>
#include <esp_camera.h>
#include <esp32-hal-log.h>
#include <esp_timer.h>
#include <aes.h>
#include <padding.h>

// 定义WiFi网络名称和密码
#define WIFI_SSID "YourSSID"
#define WIFI_PASS "YourPassword"

// 定义服务器地址和端口号
#define SERVER_ADDR "192.168.1.100"
#define SERVER_PORT 65432

// 定义加密密钥和初始向量
unsigned char key[] = {0xe2, 0x03, 0x2a, 0x86, 0xb3, 0xe4, 0xfa, 0xb3, 0xf3, 0xd8, 0xbe, 0x1e, 0x42, 0xd9, 0x4b, 0x9a};
unsigned char iv[] = {0x46, 0x26, 0xcc, 0x53, 0x83, 0x3a, 0x24, 0x89, 0xd9, 0xb1, 0x13, 0x3e, 0x6c, 0x40, 0x2b, 0x4d};

// 定义发送数据的函数
void send_data(char* student_id, uint8_t* image_data, size_t image_size) {
    // 创建AES加密上下文
    AES128_CBC_encrypt_ctx ctx;
    AES_CBC_encrypt_init(&ctx, key, iv);

    // 对图像数据进行填充和加密
    uint8_t* out_data = (uint8_t*)malloc(image_size + AES_BLOCK_SIZE);
    memset(out_data, 0, image_size + AES_BLOCK_SIZE);
    Padding_add_PKCS7(image_data, image_size, AES_BLOCK_SIZE);
    AES_CBC_encrypt_buffer(&ctx, out_data, image_data, image_size + AES_BLOCK_SIZE);

    // 将加密后的图像数据转换为十六进制字符串
    char* hex_data = (char*)malloc((image_size + AES_BLOCK_SIZE) * 2 + 1);
    memset(hex_data, 0, (image_size + AES_BLOCK_SIZE) * 2 + 1);
    for (size_t i = 0; i < image_size + AES_BLOCK_SIZE; i++) {
        snprintf(hex_data + i * 2, (image_size + AES_BLOCK_SIZE) * 2 - i * 2, "%02x", out_data[i]);
    }

    // 构造JSON数据
    char json_data[1024];
    snprintf(json_data, 1024, "{\"id\": \"%s\", \"image\": \"%s\"}", student_id, hex_data);

    // 发送JSON数据到服务器
    WiFiClient client;
    HTTPClient http;
    http.begin(client, "http://" SERVER_ADDR ":" STRINGIZE(SERVER_PORT));
    http.addHeader("Content-Type", "application/json");
    int http_code = http.POST(json_data);
    if (http_code == HTTP_CODE_OK) {
        Serial.println("Sent data to server: " + String(json_data));
    } else {
        Serial.println("Failed to send data to server");
    }
    http.end();

    // 释放内存
    free(out_data);
    free(hex_data);
}

void setup() {
    // 初始化串口，用于输出日志
    Serial.begin(115200);
    Serial.setDebugOutput(true);

    // 连接WiFi网络
    WiFi.begin(WIFI_SSID, WIFI_PASS);
    while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.println("Connecting to WiFi...");
    }
    Serial.println("Connected to WiFi");

    // 初始化摄像头
    camera_config_t config;
    config.ledc_channel = LEDC_CHANNEL_0;
    config.ledc_timer = LEDC_TIMER_0;
    config.pin_d0 = Y2_GPIO_NUM;
    config.pin_d1 = Y3_GPIO_NUM;
    config.pin_d2 = Y4_GPIO_NUM;
    config.pin_d3 = Y5_GPIO_NUM;
    config.pin_d4 = Y6_GPIO_NUM;
    config.pin_d5 = Y7_GPIO_NUM;
    config.pin_d6 = Y8_GPIO_NUM;
    config.pin_d7 = Y9_GPIO_NUM;
    config.pin_xclk = XCLK_GPIO_NUM;
    config.pin_pclk = PCLK_GPIO_NUM;
    config.pin_vsync = VSYNC_GPIO_NUM    config.pin_href = HREF_GPIO_NUM;
    config.pin_sscb_sda = SIOD_GPIO_NUM;
    config.pin_sscb_scl = SIOC_GPIO_NUM;
    config.pin_pwdn = PWDN_GPIO_NUM;
    config.pin_reset = RESET_GPIO_NUM;
    config.xclk_freq_hz = 20000000;
    config.pixel_format = PIXFORMAT_GRAYSCALE;
    config.frame_size = FRAMESIZE_QVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
    esp_err_t err = esp_camera_init(&config);
    if (err != ESP_OK) {
        Serial.printf("Failed to initialize camera (error code %d)\n", err);
        return;
    }

    // 设置图像质量和大小
    sensor_t* sensor = esp_camera_sensor_get();
    sensor->set_quality(sensor, 12);
    sensor->set_framesize(sensor, FRAMESIZE_QVGA);

    // 延迟2秒钟，等待摄像头稳定
    delay(2000);
}

void loop() {
    // 获取学号
    char student_id[] = "123456";

    // 获取图像数据
    camera_fb_t* fb = esp_camera_fb_get();
    if (!fb) {
        Serial.println("Failed to get camera frame buffer");
        return;
    }
    uint8_t* image_data = fb->buf;
    size_t image_size = fb->len;

    // 发送数据到服务器
    send_data(student_id, image_data, image_size);

    // 释放图像帧缓冲区
    esp_camera_fb_return(fb);

    // 延迟10秒钟，等待下一次拍摄
    delay(10000);
}